/**
 * 
 */
package uit.tkorg.coauthorgraph.bo;

import java.util.ArrayList;
import java.util.HashMap;
import uit.tkorg.coauthorgraph.dbaccess.AuthorMapper;
import uit.tkorg.coauthorgraph.dbaccess.AuthorPaperMapper;
import uit.tkorg.coauthorgraph.dbaccess.ConferenceMapper;

/**
 * @author Huynh Ngoc Tin
 *
 */
public class AuthorPaperBO {
    /**
     * insert a new author into the DB
     * @param authorDTO
     * @throws Exception
     */
    public void insertNewAuthorPaper(int authorID, int paperID, int author_OrderNum) throws Exception {
        AuthorPaperMapper mapper = null;
        try {
            mapper = new AuthorPaperMapper();
            mapper.insertNewAuthorPaper(authorID, paperID, author_OrderNum);
        }
        catch (Exception e) {
            throw e;
        }
        finally {
            mapper.closeConnection();
        }
    }

    /**
     * get the list CoAuthor of the specified author
     * @param authorName
     * @return
     * @throws Exception
     */
    public ArrayList getCoAuthorList(String authorName) throws Exception {
        ArrayList coAuthorList = new ArrayList();
        ArrayList paperIDList = new ArrayList();
        AuthorMapper authormapper = null;
        AuthorPaperMapper authorPaperMapper = null;
        try {
            authormapper = new AuthorMapper();
            authorPaperMapper = new AuthorPaperMapper();
            int authorID = authormapper.getAuthorID(authorName);
            if (authorID != -1) {
                // get all papers relate to this authorID
                paperIDList = authorPaperMapper.getPaperIDListOfAnAuthor(authorID);
                coAuthorList = authorPaperMapper.getCoAuthorDTOList(paperIDList, authorID);
            }

            return coAuthorList;
        }
        catch (Exception e) {
            throw e;
        }
        finally {
            authormapper.closeConnection();
            authorPaperMapper.closeConnection();
        }
    }
    
     /**
     * get the list CoAuthor of the specified author (base on authorID)
     * @param authorName
     * @return
     * @throws Exception
     */
    public ArrayList getCoAuthorList(int authorID) throws Exception {
        ArrayList coAuthorList = new ArrayList();
        ArrayList paperIDList = new ArrayList();
        AuthorMapper authormapper = null;
        AuthorPaperMapper authorPaperMapper = null;
        try {
            authormapper = new AuthorMapper();
            authorPaperMapper = new AuthorPaperMapper();
            // get all papers relate to this authorID
            paperIDList = authorPaperMapper.getPaperIDListOfAnAuthor(authorID);
            coAuthorList = authorPaperMapper.getCoAuthorDTOList(paperIDList, authorID);
            return coAuthorList;
        }
        catch (Exception e) {
            throw e;
        }
        finally {
            authormapper.closeConnection();
            authorPaperMapper.closeConnection();
        }
    }

    /**
     * check if the importAuthorID and insertPaperID existed in 'authorpaper' table or not.
     * @param importAuthorID
     * @param insertPaperID
     * @return
     * @throws Exception
     */
    public boolean isAuthorPaperExist(int importAuthorID, int insertPaperID) throws Exception {
        AuthorPaperMapper mapper = null;
        try {
            mapper = new AuthorPaperMapper();
            return mapper.isAuthorPaperExist(importAuthorID, insertPaperID);
        }
        catch (Exception e) {
            throw e;
        }
        finally {
            mapper.closeConnection();
        }
    }

    /**
     * Metrics #1: getTotalPaperInEachConfOfAuthorList
     * @param authorIDList
     * @return
     * @throws Exception
     */
    public HashMap getTotalPaperInEachConfOfAuthorList(ArrayList authorIDList) throws Exception {
        AuthorPaperMapper mapper = null;
        try {
            mapper = new AuthorPaperMapper();
            return mapper.getTotalPaperInEachConfOfAuthorList(authorIDList);
        }
        catch (Exception e) {
            throw e;
        }
        finally {
            mapper.closeConnection();
        }
    }

    /**
     * Metrics #1: getTotalPaperInEachJourOfAuthorList
     * @param authorIDList
     * @return
     * @throws Exception
     */
    public HashMap getTotalPaperInEachJourOfAuthorList(ArrayList authorIDList) throws Exception {
        AuthorPaperMapper mapper = null;
        try {
            mapper = new AuthorPaperMapper();
            return mapper.getTotalPaperInEachJourOfAuthorList(authorIDList);
        }
        catch (Exception e) {
            throw e;
        }
        finally {
            mapper.closeConnection();
        }
    }

    /**
     * countTotalPaperOfAuthor(String authorName)
     * @param authorName
     * @return
     * @throws Exception
     */
    public double countTotalPaperOfAuthor(String authorName) throws Exception {
        AuthorMapper authorMapper = new AuthorMapper();
        AuthorPaperMapper authorPaperMapper = new AuthorPaperMapper();
        try {
            int authorID = authorMapper.getAuthorID(authorName);
            return authorPaperMapper.countTotalPaperOfAnAuthor(authorID);
        }
        catch (Exception e) {
            throw e;
        }
        finally {
            authorMapper.closeConnection();
            authorPaperMapper.closeConnection();
        }
    }

    /**
     * countTotalPaperOfAuthorIDList: count the total paper of an authorID list
     * @param authorIDList
     * @return
     * @throws Exception
     */
    public double countTotalPaperOfAuthorIDList(ArrayList authorIDList) throws Exception {
        double totalPaperOfAuthorIDList = 0;
        AuthorPaperMapper authorPaperMapper = new AuthorPaperMapper();
        try {
            for (int i = 0; i < authorIDList.size(); i++) {
                int authorID = ((Integer) authorIDList.get(i)).intValue();
                totalPaperOfAuthorIDList += authorPaperMapper.countTotalPaperOfAnAuthor(authorID);
            }
        }
        catch (Exception e) {
            throw e;
        }
        finally {
            authorPaperMapper.closeConnection();
        }
        return totalPaperOfAuthorIDList;
    }

    /**
     * countTotalPaperOfAnAuthorInConfList
     * @param authorIDList
     * @param initConfNameList
     * @return
     * @throws Exception
     */
    public double countTotalPaperOfAnAuthorInConfList(int authorID, ArrayList initConfNameList) throws Exception {
        double totalPaperOfAnAuthorInConfList = 0;
        AuthorPaperMapper authorPaperMapper = new AuthorPaperMapper();
        try {
            for (int i=0; i<initConfNameList.size(); i++) {
                String confName = (String) initConfNameList.get(i);
                totalPaperOfAnAuthorInConfList += authorPaperMapper.countTotalPaperInConfOfAnAuthor(authorID, confName);
            }
        }
        catch (Exception e) {
            throw e;
        }
        finally {
            authorPaperMapper.closeConnection();
        }
        return totalPaperOfAnAuthorInConfList;
    }

    /**
     * countTotalPaperOfAuthorIDListInConfList
     * @param authorIDList
     * @param initConfNameList
     * @return
     * @throws Exception
     */
    public double countTotalPaperOfAuthorIDListInConfList(ArrayList authorIDList, ArrayList initConfNameList) throws Exception {
        double totalPaperOfAuthorIDListInConfList = 0;
        AuthorPaperMapper authorPaperMapper = new AuthorPaperMapper();
        try {
            for (int i = 0; i < authorIDList.size(); i++) {
                int authorID = ((Integer) authorIDList.get(i)).intValue();
                for (int j=0; j<initConfNameList.size(); j++) {
                    String confName = (String) initConfNameList.get(j);
                    totalPaperOfAuthorIDListInConfList += authorPaperMapper.countTotalPaperInConfOfAnAuthor(authorID, confName);
                }
            }
        }
        catch (Exception e) {
            throw e;
        }
        finally {
            authorPaperMapper.closeConnection();
        }
        return totalPaperOfAuthorIDListInConfList;
    }

    /**
     * countTotalPaperInNetwork
     * @param authorIDList
     * @param confNameList
     * @return
     * @throws Exception
     */
    public double countTotalPaperOfAuthorIDList(ArrayList authorIDList, ArrayList confNameList) throws Exception {
        double totalPaperInNetwork = 0;
        AuthorPaperMapper authorPaperMapper = new AuthorPaperMapper();
        try {
            for (int i=0; i<confNameList.size(); i++) {
                String confName = (String) confNameList.get(i);
                double totalPaperInOneConference = 0;
                for (int j=0; j<authorIDList.size(); j++) {
                    int curAuthorID = ((Integer) authorIDList.get(j)).intValue() ;
                    double totalPaperOfAuthorInConf = authorPaperMapper.countTotalPaperInConfOfAnAuthor(curAuthorID, confName);
                    totalPaperInOneConference += totalPaperOfAuthorInConf;
                }
                totalPaperInNetwork += totalPaperInOneConference;
            }
        }
        catch (Exception e) {
            throw e;
        }
        finally {
            authorPaperMapper.closeConnection();
        }
        return totalPaperInNetwork;
    }

    /**
     * calculateTotalPaperInOneConference
     * @param authorIDList
     * @param confName
     * @return
     * @throws Exception
     */
    public double countTotalPaperInOneConference(ArrayList authorIDList, String confName) throws Exception {
        AuthorPaperMapper authorPaperMapper = new AuthorPaperMapper();
        double totalPaperInOneConference = 0;
        try {
            for (int j=0; j<authorIDList.size(); j++) {
                int curAuthorID = ((Integer)authorIDList.get(j)).intValue() ;
                double totalPaperOfAuthorInConf = authorPaperMapper.countTotalPaperInConfOfAnAuthor(curAuthorID, confName);
                totalPaperInOneConference += totalPaperOfAuthorInConf;
            }
        }
        catch (Exception e) {
            throw e;
        }
        finally {
            authorPaperMapper.closeConnection();
        }

        return totalPaperInOneConference;
    }

    /**
     * calculateTotalPaperInEachConference
     * @param authorIDList
     * @param confNameList
     * @return
     * @throws Exception
     */
    public HashMap calculateTotalPaperInEachConference(ArrayList authorIDList, ArrayList confNameList) throws Exception {
        HashMap totalPaperConfHashMap = new HashMap();
        AuthorPaperMapper authorPaperMapper = new AuthorPaperMapper();
        try {
            for (int i=0; i<confNameList.size(); i++) {
                String confName = (String) confNameList.get(i);
                double sum = 0;
                for (int j=0; j<authorIDList.size(); j++) {
                    int curAuthorID = ((Integer) authorIDList.get(j)).intValue();
                    double totalPaperOfAuthorInConf = authorPaperMapper.countTotalPaperInConfOfAnAuthor(curAuthorID, confName);
                    sum += totalPaperOfAuthorInConf;
                }

                totalPaperConfHashMap.put(confName, new Double(sum));
            }
        }
        catch (Exception e) {
            throw e;
        }
        finally {
            authorPaperMapper.closeConnection();
        }

        return totalPaperConfHashMap;
    }

    /**
     * Metrics #2: calculateTotalConferencePercentage
     * @param authorIDList
     * @return
     * @throws Exception
     */
    public HashMap calculateTotalConferencePercentage(ArrayList authorIDList) throws Exception {
        HashMap confPaperPercentHashMap = new HashMap();
        ConferenceMapper confMapper = new ConferenceMapper();
        AuthorPaperMapper authorPaperMapper = new AuthorPaperMapper();
        try {
            ArrayList confNameList = confMapper.getConferenceNameListForAuthorList(authorIDList);
            for (int i=0; i<confNameList.size(); i++) {
                String confName = (String) confNameList.get(i);
                double percentSum = 0;
                for (int j=0; j<authorIDList.size(); j++) {
                    int curAuthorID = Integer.parseInt((String) authorIDList.get(j)) ;
                    double totalPaperOfAuthor = authorPaperMapper.countTotalPaperOfAnAuthor(curAuthorID);
                    double totalPaperOfAuthorInConf = authorPaperMapper.countTotalPaperInConfOfAnAuthor(curAuthorID, confName);
                    double percentPaperOfAuthorInConf = totalPaperOfAuthorInConf/totalPaperOfAuthor;
                    percentSum += percentPaperOfAuthorInConf;
                }
                confPaperPercentHashMap.put(confName, new Double(percentSum));
            }
        }
        catch (Exception e) {
            throw e;
        }
        finally {
            confMapper.closeConnection();
            authorPaperMapper.closeConnection();
        }

        return confPaperPercentHashMap;
    }

    /**
     * calculateTotalConferencePercentage
     * @param authorIDList
     * @param confNameList
     * @return
     * @throws Exception
     */
    public HashMap calculateTotalConferencePercentage(ArrayList authorIDList, ArrayList confNameList) throws Exception {
        HashMap confPaperPercentHashMap = new HashMap();
        AuthorPaperMapper authorPaperMapper = new AuthorPaperMapper();
        try {
            for (int i=0; i<confNameList.size(); i++) {
                String confName = (String) confNameList.get(i);
                double percentSum = 0;
                for (int j=0; j<authorIDList.size(); j++) {
                    int curAuthorID = ((Integer) authorIDList.get(j)).intValue() ;
                    double totalPaperOfAuthor = authorPaperMapper.countTotalPaperOfAnAuthor(curAuthorID);
                    double totalPaperOfAuthorInConf = authorPaperMapper.countTotalPaperInConfOfAnAuthor(curAuthorID, confName);
                    double percentPaperOfAuthorInConf = totalPaperOfAuthorInConf/totalPaperOfAuthor;
                    percentSum += percentPaperOfAuthorInConf;
                }

                confPaperPercentHashMap.put(confName, new Double(percentSum));
            }
        }
        catch (Exception e) {
            throw e;
        }
        finally {
            authorPaperMapper.closeConnection();
        }

        return confPaperPercentHashMap;
    }

    /**
     * Metrics #3: calculateTotalConfPercentWithCoAuthor
     * @param authorVertexIDList
     * @param initialAuthorIDList
     * @return
     * @throws Exception
     */
    public HashMap calculateTotalConfPercentWithCoAuthor(ArrayList authorVertexIDList, ArrayList initialAuthorIDList) throws Exception {
        ConferenceMapper confMapper = new ConferenceMapper();
        AuthorPaperMapper authorPaperMapper = new AuthorPaperMapper();

        HashMap totalConfPercentWithCoAuthorHashMap = new HashMap();
        try {
            ArrayList confNameList = confMapper.getConferenceNameListForAuthorList(authorVertexIDList);

            // Loop through all of conferences in the CoAuthor-Network
            for (int i=0; i<confNameList.size(); i++) {
                String confName = (String) confNameList.get(i);
                double sumConfPercentWithCoAuthor = 0;
                for (int j=0; j<initialAuthorIDList.size(); j++) {
                    double curTotalConfPercentWithCoAuthor = 0;
                    int curInitialAuthorID = ((Integer) initialAuthorIDList.get(j)).intValue();

                    // get % papers of curInitialAuthorID in the current conference
                    double totalPaperOfCurInitialAuthorInConf = authorPaperMapper.countTotalPaperInConfOfAnAuthor(curInitialAuthorID, confName);
                    double totalPaperOfCurInitialAuthor = authorPaperMapper.countTotalPaperOfAnAuthor(curInitialAuthorID);
                    double percentPaperOfCurInitialAuthorInConf = totalPaperOfCurInitialAuthorInConf/totalPaperOfCurInitialAuthor;

                    // get the Co-AuthorList of curInitialAuthorID
                    ArrayList coAuthorIDList = authorPaperMapper.getCoAuthorIDList(curInitialAuthorID);

                    // Loop through all co-authors of curInitialAuthorID
                    for (int k=0; k<coAuthorIDList.size(); k++) {
                        int coAuthorID = ((Integer) coAuthorIDList.get(k)).intValue();
                        // get % papers of coAuthorID in the current conference
                        double totalPaperOfAnCoAuthorInConf = authorPaperMapper.countTotalPaperInConfOfAnAuthor(coAuthorID, confName);
                        double totalPaperOfAnCoAuhor = authorPaperMapper.countTotalPaperOfAnAuthor(coAuthorID);
                        double percentPaperOfCoAuthorInConf = totalPaperOfAnCoAuthorInConf/totalPaperOfAnCoAuhor;
                        // count the number of papers which coAuthorID & curInitialAuthorID is the co-author
                        double numberOfPapersCoAuthor = authorPaperMapper.countTotalPaperOfTwoAuthorIsCoAuthor(curInitialAuthorID, coAuthorID);

                        curTotalConfPercentWithCoAuthor += (percentPaperOfCurInitialAuthorInConf + percentPaperOfCoAuthorInConf)
                                                                *numberOfPapersCoAuthor;
                    } // end of while (loop all of co-authors)

                    sumConfPercentWithCoAuthor += curTotalConfPercentWithCoAuthor;
                }

                totalConfPercentWithCoAuthorHashMap.put(confName, new Double(sumConfPercentWithCoAuthor));
            } // end of while(...)
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            confMapper.closeConnection();
            authorPaperMapper.closeConnection();
        }

        return totalConfPercentWithCoAuthorHashMap;
    }

    /**
     * Metric #3: calculateTotalConfPercentWithCoAuthor
     * @param authorVertexIDList
     * @param initialAuthorIDList
     * @param confNameList
     * @return
     * @throws Exception
     */
    public HashMap calculateTotalConfPercentWithCoAuthor(ArrayList authorVertexIDList, ArrayList initialAuthorIDList, ArrayList confNameList) throws Exception {
        ConferenceMapper confMapper = new ConferenceMapper();
        AuthorPaperMapper authorPaperMapper = new AuthorPaperMapper();

        HashMap totalConfPercentWithCoAuthorHashMap = new HashMap();
        try {
            // Loop through all of conferences in the list - 16 conference_classification for testing
            for (int i=0; i<confNameList.size(); i++) {
                String confName = (String) confNameList.get(i);
                double sumConfPercentWithCoAuthor = 0;
                for (int j=0; j<initialAuthorIDList.size(); j++) {
                    double curTotalConfPercentWithCoAuthor = 0;
                    int curInitialAuthorID = ((Integer) initialAuthorIDList.get(j)).intValue();

                    // get % papers of curInitialAuthorID in the current conference
                    double totalPaperOfCurInitialAuthorInConf = authorPaperMapper.countTotalPaperInConfOfAnAuthor(curInitialAuthorID, confName);
                    double totalPaperOfCurInitialAuthor = authorPaperMapper.countTotalPaperOfAnAuthor(curInitialAuthorID);
                    double percentPaperOfCurInitialAuthorInConf = totalPaperOfCurInitialAuthorInConf/totalPaperOfCurInitialAuthor;

                    // get the Co-AuthorList of curInitialAuthorID
                    ArrayList coAuthorIDList = authorPaperMapper.getCoAuthorIDList(curInitialAuthorID);

                    // Loop through all co-authors of curInitialAuthorID
                    for (int k=0; k<coAuthorIDList.size(); k++) {
                        int coAuthorID = ((Integer) coAuthorIDList.get(k)).intValue();
                        // get % papers of coAuthorID in the current conference
                        double totalPaperOfAnCoAuthorInConf = authorPaperMapper.countTotalPaperInConfOfAnAuthor(coAuthorID, confName);
                        double totalPaperOfAnCoAuhor = authorPaperMapper.countTotalPaperOfAnAuthor(coAuthorID);
                        double percentPaperOfCoAuthorInConf = totalPaperOfAnCoAuthorInConf/totalPaperOfAnCoAuhor;
                        // count the number of papers which coAuthorID & curInitialAuthorID is the co-author
                        double numberOfPapersCoAuthor = authorPaperMapper.countTotalPaperOfTwoAuthorIsCoAuthor(curInitialAuthorID, coAuthorID);

                        curTotalConfPercentWithCoAuthor += (percentPaperOfCurInitialAuthorInConf + percentPaperOfCoAuthorInConf)
                                                                *numberOfPapersCoAuthor;
                    } // end of while (loop all of co-authors)

                    sumConfPercentWithCoAuthor += curTotalConfPercentWithCoAuthor;
                }

                totalConfPercentWithCoAuthorHashMap.put(confName, new Double(sumConfPercentWithCoAuthor));
            } // end of while(...)
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            confMapper.closeConnection();
            authorPaperMapper.closeConnection();
        }

        return totalConfPercentWithCoAuthorHashMap;
    }
}
